package top.riske.gen3d.service.impl;

import com.alibaba.dashscope.aigc.generation.Generation;
import com.alibaba.dashscope.aigc.generation.GenerationParam;
import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.alibaba.dashscope.common.Message;
import com.alibaba.dashscope.common.ResultCallback;
import com.alibaba.dashscope.common.Role;
import com.alibaba.dashscope.exception.ApiException;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.dashscope.utils.Constants;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import top.riske.gen3d.service.DataReceivedCallback;
import top.riske.gen3d.service.DeepSeekService;

import java.io.IOException;
import java.util.Arrays;
import java.util.concurrent.Semaphore;

/**
 * created by vital on 2025/3/16 下午12:35
 */
@Slf4j
@Service
public class DeepSeekServiceImpl implements DeepSeekService {

    @Resource
    private RestTemplate restTemplate;

    @Value("${gen3d.ali.key}")
    private String API_KEY;

    // 系统消息
    private static final String SystemMessage = "你是一个推荐助手，请根据给你的target,以及allJobList," +
            "从以及allJobList的每一个text字段中，查询与target相似的信息，最后给到我用户可能对系统已有的哪几个模型感兴趣。" +
            "返回格式为JSON,返回推荐的id号,没有则返回空,{recommend:[2,3,5]}" +
            "不要markdown(不要有```json),如{\"recommend\": [200, 399]}";

    /**
     * 聊天接口，流式接口，通过回调函数获取结果
     * @param message 提问的问题
     */
    @Override
    public void chatWithDeepseek(String message, DataReceivedCallback callback) {
        //初始化Generation实例gen和Message实例userMsg
        Generation gen = new Generation();
        // 系统消息
        Message systemMsg = Message.builder().role(Role.SYSTEM.getValue()).content(SystemMessage).build();
        // 用户消息
        Message userMsg = Message.builder().role(Role.USER.getValue()).content(message).build();

        try {
            // 实现DataReceivedCallback接口，并处理每次接收到的数据，将消息返回
            this.streamCallWithCallback(gen, systemMsg, userMsg, callback);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    /**
     * 异步调用，通过回调函数获取结果
     * @param gen
     * @param userMsg
     * @param callback 回调函数
     * @throws ApiException
     * @throws InterruptedException
     */
    public void streamCallWithCallback(Generation gen, Message systemMsg, Message userMsg, DataReceivedCallback callback)
            throws ApiException, NoApiKeyException, InputRequiredException, InterruptedException {
        Constants.apiKey=this.API_KEY;
        //构造API请求参数，系统信息+用户信息
        GenerationParam param = buildGenerationParam(systemMsg,userMsg);
        //初始化一个信号量，用于在异步操作完成后通知主线程
        Semaphore semaphore = new Semaphore(0);
        StringBuffer fullContent = new StringBuffer();
        // 调用API，并通过回调函数返回结果
        gen.streamCall(param, new ResultCallback<GenerationResult>() {
            //有结果响应时：
            @Override
            public void onEvent(GenerationResult message) {
                String msg = message.getOutput().getChoices().get(0).getMessage().getContent();
                fullContent.append(msg);
                //返回每次接收到的消息
                try {
                    callback.onDataReceived(msg);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            //异常处理
            @Override
            public void onError(Exception err) {
                log.error("deepseek错误：", err.getMessage());
                semaphore.release();
            }

            //API调用完全结束后
            @Override
            public void onComplete() {
                log.info("Completed");
                try {
                    callback.onProcessCompleted(fullContent.toString());
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                semaphore.release();
            }
        });

        // 主线程在此等待，直到信号量被释放。
        semaphore.acquire();
    }

    /**
     * 构造API请求参数
     * @param userMsg
     * @return
     */
    private  GenerationParam buildGenerationParam(Message systemMsg,Message userMsg) {
        return GenerationParam.builder()
                .model("deepseek-v3")
                .messages(Arrays.asList(systemMsg,userMsg))
                .resultFormat(GenerationParam.ResultFormat.MESSAGE)
                .topP(0.8)
                .incrementalOutput(true)
                .build();
    }

}
